<?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
 * ExpressionEngine Channel Tools
 *
 * @version		1.0
 * @author		Jayson Ng
 * @link		http://rxwebservices.com
 */
class Channel_tools {

	private $EE;
	public $return_obj;	
	
    function Channel_tools()
    {
    	$this->EE =& get_instance();
    	$this->EE->load->model('channel_entries_model');
    	
		$this->EE->load->library('api');
		$this->EE->api->instantiate('channel_entries');
		$this->EE->api->instantiate('channel_fields');
    }

	/**
	 * Create New Entry
	 *
	 * @param object
	 * @param string
	 * @return object
	 */
	function create_entry($entry = NULL, $channel_name = NULL, $status = 'open', $dst_enabled = 'n', $versioning_enabled = 'y')
	{
		// Check if $entry of $channel_name is null
		// if so, return FALSE
		if ($entry == NULL OR $channel_name == NULL)
		{
			show_error('$entry or $channel_name is NULL - this cannot be. FIX IT.');
			return FALSE;
		}
				
		// Get channel_id
		$query								= $this->EE->db->get_where('channels', array('channel_name'=>$channel_name),1);
		$channel							= $query->row();
		
		// Set $title variable
		// Check if $entry is an object.
		if(is_object($entry) AND isset($entry->title)) {
			$title = $entry->title;
		} else {
			$title = $entry;
		}
		
		// Set Defaults
		$entry_date			= time();
		$data 				= array(
						'channel_id'				=> $channel->channel_id,
						'f_group'					=> NULL,
						'entry_id'					=> NULL,
						'allow_comments'			=> 'y',
						'title'						=> $title,
						'url_title' 				=> url_title($title, 'underscore', TRUE),
						'entry_date'				=> $entry_date,
						'edit_date'					=> $entry_date,
						'versioning_enabled'		=> $versioning_enabled,
						'status'					=> $status,
						'dst_enabled' 				=> $dst_enabled, 
						'ping_errors'				=> FALSE,
						'ping_servers'				=> array(),
					 );

		// Check if $entry is an object.
		// if it is, add to data array.
		// This is where your custom data that has been passed 
		// will override defaults.
		// Make sure you use the keys.
		if (is_object($entry))
		{
			foreach ($entry as $key => $value)
			{
				$data[$key]					= $value;
			}
			
			// Override $title;
			if (isset($entry->title))
			{
				$title 						= $entry->title;
			}
		}
		
		if($this->EE->api_channel_entries->submit_new_entry($channel->channel_id, $data) === FALSE)
		{
			show_error('An Error Occurred Creating the Entry');
		}

		// reset api_channel_entries->entry_id to 0;
		// This is a fix for bug.
		$this->EE->api_channel_entries->entry_id = 0;
				
		$last_entry 						= $this->get_most_recent_entry_id();
		$last_entry							= $this->array_to_object($last_entry);
		$this->return_obj					= $this->get_entry_by_id($last_entry->entry_id, $last_entry->channel_id);

		return	$this->return_obj;
	}  



	/**
	 * get channel entry details by (default) title
	 *
	 * Channel_obj requires
	 *  channel_id
	 *  channel_value
	 *  channel_column
	 * @return obj
	 */
	function get_entry_by($value = NULL, $channel_obj = NULL, $by = 'title', $site_id = 1)
	{	

		// Place Where 
		$where_array = array($by => $value);

		// CHANNEL details
		if (is_object($channel_obj) != NULL) {
			// Set Channel defaults to NULL
			$channel_obj_defaults 			= new stdClass();
			$channel_obj_defaults->id		= NULL;
			$channel_obj_defaults->value	= NULL;
			$channel_obj_defaults->column	= 'channel_name';
			
			foreach($channel_obj_defaults as $key => $value) {
				if (!isset($channel_obj->$key) OR $channel_obj->$key == NULL) {
					$channel_obj->$key = $value;
				}
			}

			if ($channel_obj->id != NULL) {
				$where_array['channel_id'] = $channel_obj->id;
			} else {
				if ($channel_obj->value != NULL) {
					$channel_id	= $this->get_channel_id($channel_obj->value, $channel_obj->column, $site_id);
					$where_array['channel_id'] 	=& $channel_id;							
				}
			}
			
		} elseif (!is_object($channel_obj) AND $channel_obj != NULL) {
			// if not object ($channel_obj)
			// then it SHOULD be the channel
			$channel 						= $channel_obj;
			$channel_obj					= new stdClass();
			$channel_obj->value	 			= $channel;
			
			// Get channel_id
			$row							= $this->get_channel_id($channel_obj->value, 'channel_name', $site_id);
			$channel_obj->id				= $row;
			$where_array['channel_id'] 		=& $channel_obj->id;								
		} else {	
			// no channel details given. find ID instead.
			$channel_obj					= new stdClass();
			$channel_obj->id	 			= NULL;
		}
				
		$this->EE->db->select($by . ', entry_id');
		$this->EE->db->where($where_array);
    	$query 								= $this->EE->db->get('channel_titles', 1);		
    	    	
		if($row = $query->row()) {
			// if something was returned / found.
			// Get entry_id
			$this->return_obj 				= $this->get_entry_by_id($row->entry_id, $channel_obj->id);
			return $this->return_obj;
		} else {
			// Nothing was found
			return FALSE;
		}
		
	} 
	
    
    /**
     * Get object ID
     *
     * @return obj
     */
    function get_entry_by_id($entry_id, $channel_id = '', $autosave = FALSE)
    {
    	$query 								= $this->EE->channel_entries_model->get_entry($entry_id, $channel_id, $autosave);
    	$this->return_obj 					= $query->row();
    	return $this->return_obj;
    }
    
    /**
     * Alias of channel_entries_model->get_entries
     *
     * @return string
     */
    function get_entries($channel_id, $additional_fields = array(), $additional_where = array())
    {
    	$query = $this->EE->channel_entries_model->get_entries($channel_id, $additional_fields, $additional_where);
    	return $query->result();
    }
    
    
    /**
     * Get channel_id given a channel_title
     *
     * @param string
     * @param string
     * @param INT
     *
     * @return INT
     */
    function get_channel_id($value = NULL, $by = 'channel_name', $site_id = 1)
    {
    	$this->EE->db->select('channel_id');
    	
    	// if $by is not set to 'channel_name' then it MUST be set to channel_title
    	($by == 'channel_name') ? NULL : $by = 'channel_title';
		$this->EE->db->where($by, $value);
		$this->EE->db->where('site_id', $site_id);
    	$query 								= $this->EE->db->get('channels');		
		$a 									= $query->row();
		return $a->channel_id; 
    }
    


    
    // --- Field specific Related Methods --------------------------------------------------------------
    
    /**
     * Helper function to make it easier to access field related methods in this library
     * 
     * @return various
     */
    function field($type = 'data', $value1 = NULL, $value2 = NULL)
    {
    	switch ($type) {
			case 'id':
				return $this->get_field_id($value1, $value2);
			break;
			
			case 'key':
				return $this->get_field_key($value1);
			break;
			
			case 'details':
				return $this->get_custom_field_details($value1, $value2);
			break;
			
			case 'data':
			default:
				return $this->get_field_data($value1, $value2);
			break;
		}
		
    }  
    
    
    
    /**
     * Get field id from given title
     *
     * @return obj
     */
    function get_field_id($title = NULL, $use_field_label = FALSE)
    {
    	if ($title == NULL)	{
			show_error('No Field Name');
			return FALSE;
		}

		// Use field_label or field_name;
		if ($use_field_label == FALSE) {
			$this->EE->db->where('field_name', $title);
		} else {
			$this->EE->db->where('field_label', $title);
		}
		
		$query = $this->EE->db->get('channel_fields');
		$row = $query->row();
	
		return $row;
    }
    
    
    /**
     * Get field label given a field name
     *
     * @return string
     */
    function get_field_key($field_name = NULL)
    {
    	$custom_field			= $this->get_field_id($field_name);
		$custom_field_id 		= $custom_field->field_id;			
		return 'field_id_' . $custom_field_id;
    }
    
    
    /**
     * Return field details
     *
     * @return object
     */
    function get_custom_field_details($field_id = NULL, $return_value = FALSE)
    {
    	if (is_string($field_id)) {
    		$field_id = $this->EE->channel_tools->get_field_id($field_id);
    	}
    	
    	$this->EE->db->where('field_id', $field_id->field_id);
    	$query 	= $this->EE->db->get('channel_fields');    	
    	
    	if($return_value === TRUE) {
    		$a 	= $query->row();
    		return $a->field_name;
    	} else {
	    	return $query->row();
    	}
    }


	/**
	 * Return field data from given key
	 *
	 * @param object
	 * @param string 
	 *
	 * @return string
	 */
	function get_field_data($item = NULL, $field = NULL)
	{
		// Get field
		if (property_exists($item, $field)) {
			return $item->$field;
		} else {
			$field		= $this->EE->channel_tools->get_custom_field_details($field);
			$field_id 	= 'field_id_'.$field->field_id;
			if(property_exists($item, $field_id)) {
				return $item->$field_id; 
			} else {
				return	FALSE;
			}
		}
		return FALSE;
	}  
	
	
	
	
	
	
    /**
     * Combine array of custom fields with channel_obj for channel submission
     *
     * Notes:
     * 1. You can set the default field_ft (either xhtml, none, etc) in config by config['default_field_ft']
     * 2. 
     *
     * @return object
     */
    function attach_custom_fields($field_array = NULL, $channel_obj = NULL)
    {
    	// Get default field_format
    	if($this->EE->config->item('default_field_ft') === NULL)
    	{
    		$default_field_ft = $this->EE->config->item('default_field_ft');
    	}
    	else
    	{
	    	$default_field_ft = 'xhtml';
    	}
    	
    	// Check if field_array is an array.
    	if (!is_array($field_array))
    	{
    		show_error('field_array needs to be an array');
    		return FALSE;
    	}
    	
    	foreach ($field_array as $key => $value)
    	{
    		$field_details 			= $this->EE->channel_tools->get_field_id($key);
			$field_id				= $field_details->field_id;
			
			if(!is_array($value))
			{
				// then we assume only value for field_id_x was passed
				$channel_obj->{'field_id_'.$field_id} = $value;
				$channel_obj->{'field_ft_'.$field_id}	= $default_field_ft;
			}
			else
			{
				$channel_obj->{'field_id_'.$field_id}	= $value['id'];
											
				// Set default field format to xhtml
				if (!isset($value['ft']))
				{
					$channel_obj->{'field_ft_'.$field_id}	= $default_field_ft;
				}
				else
				{
					$channel_obj->{'field_ft_'.$field_id}	= $value['ft'];
				}
			}			
    	}
		return $channel_obj;
    }  
    
     
    
    /**
     * Return channel_entry object that is related to by channel_id
     *
     * @return obj
     */
    function get_related_entry($field = NULL, $item = NULL, $get_id_of = 'child')
    {
/*
		$custom_field			= $this->get_field_id($field);
		$custom_field_id 		= $custom_field->field_id;			
		$field_id				= 'field_id_' . $custom_field_id;
    
*/
    	$field_id				= $this->get_field_key($field);
    	
    	if (!is_object($item) OR $item == NULL)
    	{
    		show_error('$item is NULL or is not an object.');
    		return FALSE;
    	}
    	
		if ($get_id_of == 'child') {
    		$this->EE->db->select('rel_child_id AS id');
    	} else {
    		$this->EE->db->select('rel_parent_id AS id');
    	}
    	
    	$this->EE->db->from('relationships');
    	$this->EE->db->where('rel_id', $item->$field_id);
    	
    	$query 	= $this->EE->db->get();
    	
    	return $query->row();
    }



	/**
	 * Checks to see if entry_id is of $cat_id
	 *
	 * @return bool
	 */
	function is_entry_of_category($entry_id = NULL, $category_id = NULL)
	{
		$this->EE->db->where('entry_id', $entry_id);
		$this->EE->db->where('cat_id', $category_id);
		$query 		= $this->EE->db->get('category_posts');
		if($query->row()) {
			return TRUE;
		} else {
			return FALSE;
		}
	}  

	/**
	 * Variant of category_model->get_channel_categories
	 * where order by cat_order
	 *
	 * @return objects
	 */
	function get_channel_categories_by_order($cat_group, $additional_fields = array(), $additional_where = array())
	{
		if ( ! is_array($additional_fields)) {
			$additional_fields = array($additional_fields);
		}

		if ( ! isset($additional_where[0]))	{
			$additional_where = array($additional_where);
		}

		if (count($additional_fields) > 0) {
			$this->EE->db->select(implode(',', $additional_fields));
		}

		$this->EE->db->select("cat_id, cat_name");
		$this->EE->db->from("categories");
		$this->EE->db->where("group_id", $cat_group);

		foreach ($additional_where as $where) {
			foreach ($where as $field => $value) {
				if (is_array($value)) {
					$this->EE->db->where_in($field, $value);
				} else {
					$this->EE->db->where($field, $value);
				}
			}
		}

		$this->EE->db->order_by('cat_order');

		return $this->EE->db->get();
	}
	


	
	/**
	 * Turns an array into an object
	 *
	 * @param @array 
	 *
	 * @return object
	 */
	function array_to_object($array = array()) 
	{
	    if (!empty($array)) {
	        $data = false;
	        foreach ($array as $akey => $aval) {
	            $data->{$akey} = $aval;
	        }
	        return $data;
	    }
    	return FALSE;
    }
	
        
    /**
	 * Get most recent entry_id
	 *
	 * @access	public
	 * @param	string
	 * @return	int
	 */
	function get_most_recent_entry_id($type = 'entry')
	{
		// By default we only grab the primary id
		$fields = array($type.'_id');
		$sort = $type.'_id';
		
		switch($type) {
			case 'comment': 
				$table = 'comments';
			break;
			
			case 'entry':
			default:
				$table = 'channel_titles';
				$fields[] = 'channel_id';
		}
		
		$this->EE->db->select($fields);
		$this->EE->db->order_by($sort, 'DESC');
		$this->EE->db->where('site_id', $this->EE->config->item('site_id'));
		
		if ($this->EE->session->userdata['can_edit_other_entries'] != 'y') {
			$this->EE->db->where('author_id', $this->EE->session->userdata['member_id']);
		}

		$q = $this->EE->db->get($table, 1);

		// Return the result if we found anything
		if ($q->num_rows() > 0)	{
			reset($fields);  // Needed due to a 5.2.1 bug (#40705)
			return (count($fields) > 1) ? $q->row_array() : $q->row(current($fields));
		}
		
		return FALSE;
	}

}




























